/**
 *  Copyright 2012 Rafal Korytkowski
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.googlecode.rapidjunit.ui.actions;

import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IActionDelegate;
import org.eclipse.ui.IObjectActionDelegate;
import org.eclipse.ui.IWorkbenchPart;

import com.googlecode.rapidjunit.RapidJUnit;
import com.googlecode.rapidjunit.finder.JUnitFinder;

/**
 * The tests updates action.
 * 
 * @author Rafal Korytkowski
 */
public class UpdateTestsActionDelegate implements IObjectActionDelegate {

	private ISelection selection;

	private JUnitFinder finder;

	public UpdateTestsActionDelegate() {
		super();
		finder = new JUnitFinder();
	}

	/**
	 * @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart)
	 */
	@Override
	public void setActivePart(IAction action, IWorkbenchPart targetPart) {
	}

	/**
	 * @see IActionDelegate#run(IAction)
	 */
	@Override
	public void run(IAction action) {
		if (!(selection instanceof IStructuredSelection)) {
			return;
		}
		Display.getDefault().asyncExec(new Runnable() {

			@Override
			public void run() {
				IStructuredSelection structuredSelection = (IStructuredSelection) selection;

				Object[] elements = structuredSelection.toArray();
				for (Object element : elements) {
					if (!(element instanceof IJavaElement)
							&& element instanceof IAdaptable) {
						element = ((IAdaptable) element)
								.getAdapter(IJavaElement.class);
					}
					addTestCases((IJavaElement) element);
				}
			}
		});
	}

	protected void addTestCases(IJavaElement element) {
		if (element instanceof ICompilationUnit) {
			IType type = (IType) ((ICompilationUnit) element).findPrimaryType();
			IType[] tests = finder.findJUnitsFor(type);
			for (IType test : tests) {
				RapidJUnit.getManager().addTestCase(type, test);
			}
		} else if (element instanceof IJavaProject) {
			try {
				for (IPackageFragmentRoot root : ((IJavaProject) element)
						.getPackageFragmentRoots()) {
					addTestCases(root);
				}
			} catch (JavaModelException e) {
				RapidJUnit.log(e);
			}
		} else if (element instanceof IPackageFragmentRoot) {
			try {
				for (IJavaElement child : ((IPackageFragmentRoot) element)
						.getChildren()) {
					addTestCases(child);
				}
			} catch (JavaModelException e) {
				RapidJUnit.log(e);
			}
		} else if (element instanceof IPackageFragment) {
			try {
				for (IJavaElement child : ((IPackageFragment) element)
						.getChildren()) {
					addTestCases(child);
				}
			} catch (JavaModelException e) {
				RapidJUnit.log(e);
			}
		}
	}

	/**
	 * @see IActionDelegate#selectionChanged(IAction, ISelection)
	 */
	@Override
	public void selectionChanged(IAction action, ISelection selection) {
		this.selection = selection;
	}

}
